/**
 * @param {ListNode} head
 * @return {ListNode}
 */
// 以链表1->2->3->4为例。
var swapPairs = function (head) {
    // 创建一个伪节点，用来淡妆第一次调换时的prevNode，以及输出最终的结果
    let dummyNode = new ListNode(-1);
    // 初始状态dummyNode.next指向head，如果当前链表长度小于2，则直接返回head。
    dummyNode.next = head;
    // 由于节点指向的交换，实际上由3个节点参与。
    // 因此对于第一次交换，需要提供一个prevNode参与。
    let prevNode = dummyNode; // 初始状态为-1
    let currentNode = head; // 初始状态为1
    let nextNode; // 不需要设置初始值，进入循环后，会设置初始状态为2
  
    // 遍历链表，当前例子的链表为-1->1->2->3->4，-1为dummyNode。
    // 注意：while循环中的注释，都指的是第一次遍历。
    // 对于第n次遍历而言，prevNode是链表的真实节点，不再是dummyNode。
    while (currentNode && currentNode.next) {
      nextNode = currentNode.next; // 获取要调换的下一个节点，即为2
  
      // 经过如下调换之后，链表变为了-1->2->1->3->4。
      currentNode.next = nextNode.next; // 1->3
      nextNode.next = currentNode; // 2->1
      prevNode.next = nextNode; // -1->2
  
      // currentNode即节点1，也就是下一次调换的prevNode.
      // 此时需要注意的是，prevNode确实被替换了。
      // 而dummyNode还是旧的prevNode(-1)，其next指向的是第一次调换后的头节点，即2.
      prevNode = currentNode;
      // 将链表向前移动
      currentNode = currentNode.next;
    }
  
    // 此时dummyNode.next其实指向的是是头两个节点调换后，真实的头节点。
    // 当链表的节点数小于2时，不会进入循环，直接返回的是当前节点head
    return dummyNode.next;
  };
//   理解中